﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.YouTube;
using Google.YouTube;

namespace YoutubeVideoManager
{
    /// <summary>
    /// Logica di interazione per VideosView.xaml
    /// </summary>
    public partial class VideosView : UserControl
    {
        enum WorkType
	    {
                Playlist, Search
	    }

        #region Event
        public event EventHandler VideoDoubleClick;
        public event EventHandler DownloadCompleted;
        #endregion

        #region Properties
        public ItemCollection Items { get { return this.lvVideos.Items; } }
        public VideoItem SelectedVideo { get { return this.lvVideos.SelectedItem as VideoItem; } }
        #endregion

        #region Fields
        BackgroundWorker worker;
        int retrieved, downloaded;
        #endregion

        #region Methods
        public VideosView()
        {
            InitializeComponent();

            worker = new BackgroundWorker();
            worker.WorkerSupportsCancellation = worker.WorkerReportsProgress = true;

            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = true;
            try
            {
                downloaded = 0;
                object[] args = e.Argument as object[];
                WorkType work = (WorkType)args[0];
                IEnumerable<Video> videos = null;

                if (work == WorkType.Playlist)
                {
                    PlaylistItem playlist = args[1] as PlaylistItem;
                    videos = playlist.Videos;
                }
                else if (work == WorkType.Search)
                {
                    string queryStr = args[1] as string;
                    YouTubeQuery query = new YouTubeQuery(YouTubeQuery.DefaultVideoUri);
                    query.OrderBy = "relevance";
                    query.Query = queryStr;
                    query.SafeSearch = YouTubeQuery.SafeSearchValues.None;
                    query.StartIndex = 0 * 25;
                    query.NumberToRetrieve = 25;

                    videos = Global.Request.Get<Video>(query).Entries;
                }

                retrieved = 0;
                foreach (Video video in videos)
                {
                    if (worker.CancellationPending)
                        return;
                    worker.ReportProgress(0, video);
                    retrieved++;
                }
            }
            catch { e.Result = false; }
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            VideoItem vi = new VideoItem(e.UserState as Video);
            vi.PreviewMouseDoubleClick += new MouseButtonEventHandler(vi_PreviewMouseDoubleClick);
            vi.DownloadCompleted += new EventHandler(vi_DownloadCompleted);
        }

        void vi_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (VideoDoubleClick != null)
                VideoDoubleClick((sender as VideoItem).Video, EventArgs.Empty);
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!(bool)e.Result || retrieved == 0)
            {
                WorkCompleted();
            }
        }

        void vi_DownloadCompleted(object sender, EventArgs e)
        {
            this.lvVideos.Items.Add(sender as VideoItem);
            if (++downloaded >= retrieved)
            {
                WorkCompleted();
            }
        }

        void WorkCompleted()
        {
            lvVideos.IsEnabled = true;
            this.prgBar.Visibility = System.Windows.Visibility.Collapsed;
            if (DownloadCompleted != null)
                DownloadCompleted(this, EventArgs.Empty);
        }

        /// <summary>
        /// Mostra il feed di video.
        /// </summary>
        /// <param name="feed"></param>
        void StartWorker(object arg, WorkType work)
        {
            lvVideos.IsEnabled = false;
            lvVideos.Items.Clear();

            this.prgBar.Visibility = System.Windows.Visibility.Visible;
            while (worker.IsBusy)
            {
                if (!worker.CancellationPending)
                    worker.CancelAsync();
            }

            worker.RunWorkerAsync(new object[] { work, arg});
        }

        public void ShowPlaylist(PlaylistItem playlist)
        {
            StartWorker(playlist, WorkType.Playlist);
        }

        public void ShowSearch(string query)
        {
            StartWorker(query, WorkType.Search);
        }
        #endregion

        private void lvVideos_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            object data = GetDataFromListBox(lvVideos, e.GetPosition(lvVideos));
            if (data != null)
                DragDrop.DoDragDrop(lvVideos, data, DragDropEffects.Copy);
        }
        static object GetDataFromListBox(ListBox source, Point point)
        {
            UIElement element = source.InputHitTest(point) as UIElement;
            if (element != null)
            {
                object data = DependencyProperty.UnsetValue;
                while (data == DependencyProperty.UnsetValue)
                {
                    data = source.ItemContainerGenerator.ItemFromContainer(element);
                    if (data == DependencyProperty.UnsetValue)
                        element = VisualTreeHelper.GetParent(element) as UIElement;
                    if (element == source)
                        return null;
                    if (data != DependencyProperty.UnsetValue)
                        return data;
                }
            }
            return null;
        }
    }
}
